package com.ywy.job.core;

import com.ywy.job.model.SysJob;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * 定时任务管理类
 *
 * @author ywy
 * @date 2021/11/5 15:32
 */
@Component
public class JobScheduledRegistrar implements DisposableBean {
    private final Map<Runnable, ScheduledFuture> scheduledTasks = new ConcurrentHashMap<>(16);

    @Autowired
    private TaskScheduler taskScheduler;

    /**
     * 添加任务
     * @param job
     */
    public void addJob(SysJob job) {
        JobRunnable runnable = new JobRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams());
        CronTask cronTask = new CronTask(runnable, job.getCronExpression());
        if (this.scheduledTasks.containsKey(runnable)) {
            deleteJob(runnable);
        }

        ScheduledFuture scheduledFuture = this.taskScheduler.schedule(runnable, cronTask.getTrigger());
        this.scheduledTasks.put(runnable, scheduledFuture);
    }

    /**
     * 删除任务
     * @param job
     */
    public void deleteJob(SysJob job) {
        JobRunnable runnable = new JobRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams());
        deleteJob(runnable);
    }

    /**
     * 删除任务
     * @param runnable
     */
    public void deleteJob(Runnable runnable) {
        ScheduledFuture scheduledFuture = this.scheduledTasks.remove(runnable);
        if (scheduledFuture != null) {
            scheduledFuture.cancel(true);
        }
    }

    /**
     * 立即触发
     * @param job
     */
    public void runJobNow(SysJob job) {
        JobRunnable runnable = new JobRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams());
        runnable.run();
    }

    @Override
    public void destroy() {
        for (ScheduledFuture scheduledFuture : this.scheduledTasks.values()) {
            scheduledFuture.cancel(true);
        }

        this.scheduledTasks.clear();
    }
}
